﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Fighter.Screens;
using Microsoft.Xna.Framework.Audio;
using Fighter.ScreenManagers;
using Fighter.Screens.Scenario;

namespace Fighter.GameContent
{
    class Munition
    {
        private Texture2D bullet;
        private GraphicsDeviceManager graphics;

        //Bullet configuration
        private Vector2 bulletLastPosition = new Vector2(100, 100);
        private float bulletSpeedX = 5;
        private float bulletSpeedY = 5;
        private int bulletDirectionX = 1;
        private int bulletDirectionY = 0;
        private Vector2 startPositionMunition;
        private Level level;
        //variable servant a masquer la munition en attendant de la supprimer
        private Boolean isDrawingUpdating = true;
        private Vector2 playerPosition;
        private Rectangle localBounds;

        // rectangle cible de l'attaque
        private Rectangle cible;

        //direction du bullet
        private int direction;

        //sound
        private SoundEffect touchSound, impactBlock;

        //getter
        public Boolean IsDrawingUpdating
        {
            get
            {
                return this.isDrawingUpdating;
            }
        }
        /// <summary>
        /// Gets a rectangle which bounds this munition in world space.
        /// </summary>
        public Rectangle BoundingRectangle
        {
            get
            {
                int left = (int)Math.Round(this.bulletLastPosition.X - bullet.Bounds.X) + localBounds.X;
                int top = (int)Math.Round(this.bulletLastPosition.Y - bullet.Bounds.Y) + localBounds.Y;

                return new Rectangle(left, top, localBounds.Width, localBounds.Height);
            }
        }

        //Gestion du scenario
        private ScreenManager screenManager;
        private Game game;
        private PlayerIndex? controllingPlayer;

        /// <summary>
        /// Construct a new Weapon.
        /// </summary>
        public Munition(Level level, Vector2 position, GraphicsDeviceManager graphics, KeyboardState keyboardState, int playerOrientation, ScreenManager screenManager, Game game, PlayerIndex? controllingPlayer)
        {
            this.level = level;
            this.graphics = graphics;
            this.bulletLastPosition = position;
            this.bulletDirectionX = playerOrientation;
            GetBulletDirection(keyboardState);
            this.playerPosition = position;
            this.screenManager = screenManager;
            this.game = game;
            this.controllingPlayer = controllingPlayer;
            LoadContent();
            ScreenManagers.StateManager.CurrentGameState = ScreenManagers.StateManager.GameState.Alive;
        }
        /// <summary>
        /// Construct a new Weapon for Boss
        /// </summary>
        public Munition(Level level, Vector2 startPositionMunition, GraphicsDeviceManager graphicsDeviceManager, Rectangle cible, int direction)
        {
            // TODO: Complete member initialization
            this.level = level;
            this.bulletLastPosition = startPositionMunition;
            this.startPositionMunition = startPositionMunition;
            this.cible = cible;
            this.graphics = graphicsDeviceManager;
            this.direction = direction;
            LoadContent();
        }

        protected void GetBulletDirection(KeyboardState keyboardState)
        {
            //on fait attention aux directions que doivent prendre les munitions
            //gauche
            if (keyboardState.IsKeyDown(Config.Instance.Left))
            {
                this.bulletDirectionX = -1;
                CheckVerticalDirection(keyboardState);
            }
            //droite
            if (keyboardState.IsKeyDown(Config.Instance.Right))
            {
                this.bulletDirectionX = 1;
                CheckVerticalDirection(keyboardState);
            }
            //haut
            if (keyboardState.IsKeyDown(Config.Instance.Up))
            {
                this.bulletDirectionY = -1;
                CheckHorizontalDirection(keyboardState);
            }
            //bas
            if (keyboardState.IsKeyDown(Config.Instance.Down))
            {
                this.bulletDirectionY = 1;
                CheckHorizontalDirection(keyboardState);
            }
        }

        protected void CheckVerticalDirection(KeyboardState keyboardState)
        {
            if (keyboardState.IsKeyDown(Config.Instance.Up))
            {
                this.bulletDirectionY = -1;
            }
            else if (keyboardState.IsKeyDown(Config.Instance.Down))
            {
                this.bulletDirectionY = 1;
            }
            else
            {
                this.bulletDirectionY = 0;
            }
        }

        protected void CheckHorizontalDirection(KeyboardState keyboardState)
        {
            if (keyboardState.IsKeyDown(Config.Instance.Left))
            {
                this.bulletDirectionX = -1;
            }
            else if (keyboardState.IsKeyDown(Config.Instance.Right))
            {
                this.bulletDirectionX = 1;
            }
            else
            {
                this.bulletDirectionX = 0;
            }
        }

        /// <summary>
        /// Loads the weapon sprite.
        /// </summary>
        public void LoadContent()
        {
            bullet = this.level.Content.Load<Texture2D>("Sprites/Player/rock");

            // Calculate bounds within texture size.
            int width = (int)(bullet.Width * 0.4 * GameplayScreen.baseScreenSize.X / (float)graphics.GraphicsDevice.PresentationParameters.BackBufferWidth);
            int left = (bullet.Width - width) / 2;
            int height = (int)(bullet.Width * 0.8 * GameplayScreen.baseScreenSize.Y / (float)graphics.GraphicsDevice.PresentationParameters.BackBufferHeight);
            int top = bullet.Height - height;
            localBounds = new Rectangle(left, top, width, height);

            //load sounds
            touchSound = this.level.Content.Load<SoundEffect>("Game/Sounds/os_broye");
            impactBlock = this.level.Content.Load<SoundEffect>("Game/Sounds/impactBlockMunition");
        }

        public void Update(
            GameTime gameTime)
        {
            if (isDrawingUpdating)
            {
                //bullet Update
                bulletLastPosition.X += bulletSpeedX * bulletDirectionX;
                bulletLastPosition.Y += bulletSpeedY * bulletDirectionY;

                // If the player is now colliding with the level, separate them.
                HandleCollisions();
            }
        }
        public void UpdateForBoss(GameTime gameTime)
        {
            bulletLastPosition.X += bulletSpeedX * direction;
            float vise = ((float)cible.Y - (float)startPositionMunition.Y + 50) / ((float)cible.X - (float)startPositionMunition.X + 50);
            bulletLastPosition.Y += vise * bulletSpeedY * direction;

        }
        /// <summary>
        /// verify if the munition touch player
        /// </summary>
        /// <returns></returns>
        public Munition munitionTouched()
        {
            if (this.BoundingRectangle.Intersects(level.Player.BoundingRectangle))
            {
                return this;
            }
            return null;
        }

        private void HandleCollisions()
        {
            // Get the player's bounding rectangle and find neighboring tiles.
            Rectangle bounds = BoundingRectangle;
            int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width);
            int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1;
            int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height);
            int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1;

            //// Reset flag to search for ground collision.
            //isOnGround = false;

            // For each potentially colliding tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = this.level.GetCollision(x, y);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = this.level.GetBounds(x, y);

                        if (collision == TileCollision.Finish)
                        {
                            //ScreenManagers.StateManager.CurrentGameState = ScreenManagers.StateManager.GameState.Death;
                            OnCollision();
                        }
                        else if (collision == TileCollision.Death)
                        {
                            //ScreenManagers.StateManager.CurrentGameState = ScreenManagers.StateManager.GameState.Death;
                            OnCollision();
                        }
                        else
                        {
                            Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                            if (depth != Vector2.Zero)
                            {
                                float absDepthX = Math.Abs(depth.X);
                                float absDepthY = Math.Abs(depth.Y);

                                // Resolve the collision along the shallow axis.
                                if (absDepthY < absDepthX || collision == TileCollision.Platform)
                                {
                                    // Ignore platforms, unless we are on the ground.
                                    if (collision == TileCollision.Impassable)
                                    {
                                        OnCollision();
                                    }
                                }
                                else if (collision == TileCollision.Impassable) // Ignore platforms.
                                {
                                    OnCollision();
                                }
                            }
                        }
                    }
                }
            }
        }

        protected void OnCollision()
        {
            isDrawingUpdating = false;
            impactBlock.Play();
        }

        public void OnTouchEnnemy(Enemy enemy, GameTime gameTime)
        {
            touchSound.Play();

            if (enemy is Teacher)
            {
                Teacher teacher = (Teacher)enemy;
                //On attend d'avoir raconter le scénario avant de pouvoir le tuer
                if (teacher.ScenarioDisplayed)
                {
                    teacher.IsAgressive = true;
                    teacher.Movement = (int)direction * 1.0f;
                }
                else
                {
                    if (!teacher.OrderDisplayed)
                    {
                        screenManager.AddScreen(new Scenario1_3Screen(this.game, this.graphics), this.controllingPlayer);
                        teacher.OrderDisplayed = true;
                    }
                }
                if (teacher.IsAgressive)
                {
                    enemy.Life -= 1;
                }
            }
            else
            {
                enemy.Life -= 1;
            }
            isDrawingUpdating = false;
        }

        /// <summary>
        /// Draws the animated weapon.
        /// </summary>
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (isDrawingUpdating)
            {
                //Draw bullet
                spriteBatch.Draw(bullet, bulletLastPosition, null, Color.White);
            }
        }
    }
}
